package com.sc.admin.core.api.open.user;


import com.sc.admin.core.service.SysMenuService;
import com.sc.admin.core.service.SysResourceService;
import com.sc.admin.core.service.SysUserService;
import com.sc.common.annotations.OpenApi;
import com.sc.common.annotations.OperationLog;
import com.sc.common.context.DefaultBusinessContext;
import com.sc.common.dto.WebResponseDto;
import com.sc.common.entity.admin.account.SysAccount;
import com.sc.common.entity.admin.user.SysUser;
import com.sc.common.enums.ApplicationEnum;
import com.sc.common.enums.OperationLogEnum;
import com.sc.common.util.CommonUtil;
import com.sc.common.util.MyStringUtils;
import com.sc.common.util.RC4;
import com.sc.common.util.cache.DataDictionaryUtil;
import com.sc.common.util.cache.SpringRedisTools;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * web员工登录：账号密码登录
 */
@Api(tags = {"开放接口~web员工账号密码登陆"})
@OpenApi
@RequestMapping("/api/open/v1/WebUserLoginByAccountOpenApi")
@RestController
public class WebUserLoginByAccountOpenApi extends WebUserLoginBase {
    static Logger logger = LogManager.getLogger(WebUserLoginByAccountOpenApi.class);

    @Autowired
    private SpringRedisTools springRedisTools;

    @Autowired
    private SysMenuService sysMenuServiceImpl;

    @Autowired
    private SysResourceService sysResourceServiceImpl;

    @Autowired
    private SysUserService sysUserServiceImpl;


    @Override
    protected SpringRedisTools getSpringRedisTools() {
        return springRedisTools;
    }

    @Override
    protected SysMenuService getSysMenuServiceImpl() {
        return sysMenuServiceImpl;
    }

    @Override
    protected SysResourceService getSysResourceServiceImpl() {
        return sysResourceServiceImpl;
    }

    @Override
    protected WebResponseDto validateAndGetUser(String loginName, String password, String code, String message, String checkCodeRC4){
        WebResponseDto responseDto = new WebResponseDto();

        if(MyStringUtils.isBlank(MyStringUtils.null2String(loginName))){
            responseDto.setFlag(WebResponseDto.INFO_WARNING);
            responseDto.setMessage("请输入登录账号");
            return responseDto;
        }

        if(MyStringUtils.isBlank(MyStringUtils.null2String(password))){
            responseDto.setFlag(WebResponseDto.INFO_WARNING);
            responseDto.setMessage("请输入登录口令");
            return responseDto;
        }

        String passwordRC4 = RC4.encry_RC4_string(password.toUpperCase(),ApplicationEnum.LOGIN_RC4_KEY.getStringValue());

        SysAccount account = DataDictionaryUtil.getAccountByCode(loginName);
        if(account == null) {
            logger.warn("登录失败：此账号[{}]不存在",loginName);
            responseDto.setFlag(WebResponseDto.INFO_WARNING);
            responseDto.setMessage("账号或密码错误"); // 不应提示太明确，防止恶意碰撞攻击
            return responseDto;
        }

        if(!passwordRC4.equals(account.getPassword())){
            logger.warn("登录失败：此账号[{}]的密码输入有误",loginName);
            responseDto.setFlag(WebResponseDto.INFO_WARNING);
            responseDto.setMessage("账号或密码错误"); // 不应提示太明确，防止恶意碰撞攻击
            return responseDto;
        }

        Map<String,Object> map = new HashMap<>(2);
        map.put("account",account);
        if("A101701".equals(account.getType())){ // 管理员，只存在account表
        }else if("A101703".equals(account.getType())){ // 员工
            SysUser user = sysUserServiceImpl.selectByPrimaryKey(account.getId());
            map.put("user",user);
        }else if("A101705".equals(account.getType())){ // 客户登录，暂时不支持客户登录web系统
            responseDto.setFlag(WebResponseDto.INFO_WARNING);
            responseDto.setMessage("您无权登录系统");
            return responseDto;
        }
        responseDto.setObj(map);
        return responseDto;
    }

    /**
     *
     * @param loginName
     * @param password
     * @param lang
     * @return
     */
    @ApiOperation(value = "Web登陆：员工通过账号密码登陆", httpMethod = "POST")
    @ApiImplicitParams({
            @ApiImplicitParam(name="loginName",value="登陆账号",required=true,paramType="query"),
            @ApiImplicitParam(name="password",value="登陆口令（使用32位小写MD5密文，如0192023a7bbd73250516f069df18b500）",required=true,paramType="query"),
            @ApiImplicitParam(name="lang",value="语言（如zh-CN）",required=true,paramType="query")
    })
    @OperationLog(moduleName= OperationLogEnum.MODULE_COMMON,businessName="Web登陆：员工通过账号密码登陆",operationType= OperationLogEnum.Login)
    @RequestMapping(value = "/login",method = RequestMethod.POST)
    public WebResponseDto login(@RequestParam("loginName") String loginName, @RequestParam("password") String password, @RequestParam("lang") String lang) {
        WebResponseDto responseDto = new WebResponseDto();

        WebResponseDto validateAndGetUserResponseDto = validateAndGetUser(loginName,password,"","","");
        if(!WebResponseDto.INFO_SUCCESS.equals(validateAndGetUserResponseDto.getFlag())){
            return validateAndGetUserResponseDto;
        }

        DefaultBusinessContext.getContext().setDataSourceId(ApplicationEnum.DEFAULT.name());

        String[] tokens = createToken(loginName);
        if (tokens.length != 2) {
            responseDto.setFlag(WebResponseDto.INFO_WARNING);
            responseDto.setMessage("登录失败");
        }else{
            Map map = (Map) validateAndGetUserResponseDto.getObj();
            SysAccount account = map.get("account") == null ? null : (SysAccount)map.get("account");
            SysUser user = map.get("user") == null ? null : (SysUser)map.get("user");

            Long accountId = account.getId();
            String accountType = account.getType();
            String permissionType = CommonUtil.getPermissionType(accountType,user == null ? "" : user.getType());

            /**
             * 解析获取当前登录用户的相关资源
             */
            final Map<String,Object> mapValue = new HashMap<>();
            appendMenuToUserContext(mapValue,accountId,accountType,permissionType,lang);
            appendMenuNameToUserContext(mapValue,permissionType,lang);
            appendAccountToUserContext(mapValue,account);
            appendUserToUserContext(mapValue,user);
            appendProjectToUserContext(mapValue,accountId);
            appendLangToUserContext(mapValue,lang);
            appendTokenToUserContext(mapValue,tokens[1]);

            responseDto.setObj(getResponseResource(accountType,permissionType,mapValue));


            /**
             * 将用户登录相关信息存储到缓存，以便解析作为上下文
             */
            String redisKey = tokens[0];
            springRedisTools.addMap(redisKey,  mapValue, ApplicationEnum.X_AUTH_TOKEN_EXPIRE_TIME.getIntValue(), TimeUnit.MINUTES);
        }
        return responseDto;
    }
}
